package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.UserWalletLogListDto;
import com.frejoys.common.dto.app.UserWalletLogDto;
import com.frejoys.common.dto.app.UserWalletLogPageDto;
import com.frejoys.common.dto.app.UserWalletLogTransferDto;
import com.frejoys.common.dto.common.IdDto;
import com.frejoys.common.dto.common.MoneyDto;
import com.frejoys.common.dto.common.PageDto;
import com.frejoys.common.enums.*;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.AppConfigUtil;
import com.frejoys.common.util.CommonUtil;
import com.frejoys.common.util.SnowflakeUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.admin.UserWalletListLogVo;
import com.frejoys.common.vo.admin.UserWalletListVo;
import com.frejoys.common.vo.app.UserWalletLogDetailsVo;
import com.frejoys.common.vo.app.UserWalletLogListVo;
import com.frejoys.common.vo.app.UserWalletLogPageVo;
import com.frejoys.dao.entity.*;
import com.frejoys.dao.mapper.*;
import com.frejoys.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserWalletLogServiceImpl extends ServiceImpl<UserWalletLogMapper, UserWalletLog> implements UserWalletLogService {

    private final UserMapper userMapper;

    private final UserService userService;

    private final PlatformService platformService;

    private final PlatformWalletLogService platformWalletLogService;

    private final UserCashMapper userCashMapper;

    private final UserCashService userCashService;

    private final OrderMapper orderMapper;

    private final StoreMapper storeMapper;

    @Override
    public boolean addInfo(Long userId, BigDecimal money, Long drawSn, Integer type, Integer createTime, Integer status) {
        return save(new UserWalletLog() {{
            setUserId(userId);
            setMoney(money);
            // setCashCharges(cashCharges);
            setDrawSn(drawSn);
            setType(type);
            setCreateTime(createTime);
            setUpdateTime(createTime);
            setStatus(status);
        }});
    }

    /**
     * 获取消费记录
     *
     * @return
     */
//    @Override
//    public List<UserWalletLogListVo> userWalletListInfo(Long userId, PageDto dto) {
//        Page page = new Page<>(dto.getPage(), dto.getSize());
//        page.setSearchCount(false);
//
//        List<UserWalletLog> userWalletLogs = new ArrayList<>();
//        List<UserWalletLogListVo> list = new ArrayList<>();
//
//        User user = userService.getInfo(userId);
//
//        if (CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue())) {
//
//            LambdaQueryWrapper<UserWalletLog> wrapper = new LambdaQueryWrapper();
//            wrapper.eq(UserWalletLog::getUserId, userId)
//                    .ge(UserWalletLog::getType, EUserWalletLogType.agentRebate.getValue())
//                    .le(UserWalletLog::getType,EUserWalletLogType.groupRebate.getValue())
//                    .orderByDesc(UserWalletLog::getCreateTime);
//
//            userWalletLogs = baseMapper.selectPage(page, wrapper).getRecords();
//        } else {
//            throw new GeneralException(HttpStatus.agentUserError);
//        }
//
//        if (!userWalletLogs.isEmpty()) {
//
//            userWalletLogs.forEach(userWalletLog -> {
//                UserWalletLogListVo vo = new UserWalletLogListVo();
//                vo.setType(userWalletLog.getType());
//                vo.setMoney(CommonUtil.getMoneyModified(userWalletLog.getMoney()));
//                vo.setDrawSn(userWalletLog.getDrawSn());
//                vo.setCashMoney(userWalletLog.getCashMoney());
//                vo.setCreateTime(userWalletLog.getCreateTime());
//                vo.setStatus(userWalletLog.getStatus());
//                list.add(vo);
//            });
//        }
//
//        return list;
//    }


    //后台分页查询用户钱包信息
    @Override
    public Page<UserWalletLogPageVo> walletLogPage(UserWalletLogPageDto dto) {
        Page<UserWalletLogPageVo> page = new Page<>(dto.getPage(), dto.getSize());
        List<UserWalletLogPageVo> userWalletLogPageVos = baseMapper.selectPageWalletLog(page, dto);
        List<UserCash> userCashes;
        Map<Long, UserCash> userCashMap = new HashMap<>();
        if(dto.getType() != null && dto.getType().equals(EUserWalletLogType.cash.getValue())) {
            LambdaQueryWrapper<UserCash> wrapper = Wrappers.lambdaQuery();
            wrapper.select(UserCash::getAccount, UserCash::getUsername, UserCash::getWxImg, UserCash::getType, UserCash::getUserId);
            userCashes = userCashMapper.selectList(wrapper);
            if(CollectionUtil.isNotEmpty(userCashes)) {
                userCashMap = userCashes.stream().collect(Collectors.toMap(UserCash::getUserId, u -> u));
            }
        }

        for(UserWalletLogPageVo u :userWalletLogPageVos){
            UserCash userCash = userCashMap.get(u.getUserId());
            u.setWxImg(AppConfigUtil.getUrlPrefix(ObjectUtil.isEmpty(userCash) ? "" : userCash.getWxImg()));
            u.setUsername(ObjectUtil.isEmpty(userCash) ? "" : userCash.getUsername());
            u.setAccount(ObjectUtil.isEmpty(userCash) ? "" : userCash.getAccount());
            u.setCashType(ObjectUtil.isEmpty(userCash) ? null : userCash.getType());
        }
        page.setRecords(userWalletLogPageVos);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean walletCash(Long userId, MoneyDto dto) {

        LambdaQueryWrapper<UserCash> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserCash::getId)
                .eq(UserCash::getUserId, userId);
        UserCash userCash = userCashService.getOnly(wrapper);

        if (userCash == null) {
            throw new GeneralException(HttpStatus.notUserCashError);
        }

        Platform platform = platformService.getInfo();

        /*
        // 计算分，元
        BigDecimal hundred = CommonUtil.integerToBigDecimal(100);

        // 计算手续费
        BigDecimal cashChargesRatio = CommonUtil.bigDecimalDivide(CommonUtil.floatToBigDecimal(platform.getUserCashChargesRatio()), hundred);
        BigDecimal cashChargesMoney = CommonUtil.bigDecimalMultiply(dto.getMoney(), cashChargesRatio);
        */

        Long drawSn = SnowflakeUtil.appNextId();
        Integer nt = TimeUtil.unixTime();

        // 添加平台手续费记录
        // platformWalletLogService.addInfo(EPlatform.agentRoleGroupId.getValue(), cashChargesMoney, drawSn, EPlatformWalletLogType.userCashCharges.getValue(), nt);

        return save(new UserWalletLog() {{
            setUserId(userId);
            // 负数
            setMoney(dto.getMoney().negate());
            // setCashMoney(dto.getMoney().subtract(cashChargesMoney));
            // setCashCharges(cashChargesMoney);
            // setCashMoney(dto.getMoney());
            // setCashCharges(BigDecimal.ZERO);
            setDrawSn(drawSn);
            setType(EUserWalletLogType.cash.getValue());
            setCreateTime(nt);
            setUpdateTime(nt + platform.getUserCashTime());
            setStatus(EPayStatus.wait.getValue());
        }});
    }

    // 后台审核用户提现
    @Override
    public boolean checkUserWalletLog(IdDto dto) {
        LambdaQueryWrapper<UserWalletLog> wrapper = Wrappers.lambdaQuery();
        wrapper.select(UserWalletLog::getUserId, UserWalletLog::getType, UserWalletLog::getStatus).eq(UserWalletLog::getId, dto.getId());
        UserWalletLog us = getOnly(wrapper);

        //只有用户提现才可申请
        if (!us.getType().equals(EUserWalletLogType.cash.getValue())) {
            throw new GeneralException(HttpStatus.applyError);
        }

        if (us.getStatus().equals(EStatus.on.getValue())) {
            throw new GeneralException(HttpStatus.moneyCashExist);
        }

        //获取对应用户
        User simpleUser = userMapper.getSimpleUser(us.getUserId());

        if (ObjectUtil.isEmpty(simpleUser)) {
            throw new GeneralException(HttpStatus.userNoExist);
        }

        if (simpleUser.getStatus() < EStatus.on.getValue()) {
            throw new GeneralException(HttpStatus.userStatusLoginError);
        }

        // return update(Wrappers.<UserWalletLog>lambdaUpdate().eq(UserWalletLog::getId,dto.getId()).set(UserWalletLog::getStatus,EStatus.on.getValue()));
        return baseMapper.upCashStatus(dto.getId(), TimeUtil.unixTime(), EPayStatus.wait.getValue(), EPayStatus.finish.getValue());
    }


    // @Override
    // public List<UserWalletLogListVo> userConsumptionWalletListInfo(Long userId, PageDto dto) {
    //     Page page = new Page<>(dto.getPage(), dto.getSize());
    //     page.setSearchCount(false);
    //
    //     List<UserWalletLogListVo> list = new ArrayList<>();
    //
    //     LambdaQueryWrapper<UserWalletLog> wrapper = new LambdaQueryWrapper();
    //     wrapper.eq(UserWalletLog::getUserId, userId)
    //             .gt(UserWalletLog::getType, EUserWalletLogType.order.getValue())
    //             .le(UserWalletLog::getType, EUserWalletLogType.orderRebate.getValue())
    //             .or().eq(UserWalletLog::getType, EUserWalletLogType.cash.getValue())
    //             .eq(UserWalletLog::getUserId, userId)
    //             .orderByDesc(UserWalletLog::getCreateTime);
    //
    //     List<UserWalletLog> userWalletLogs = baseMapper.selectPage(page, wrapper).getRecords();
    //
    //     if (!userWalletLogs.isEmpty()) {
    //
    //         userWalletLogs.forEach(userWalletLog -> {
    //             UserWalletLogListVo vo = new UserWalletLogListVo();
    //             vo.setType(userWalletLog.getType());
    //             vo.setMoney(userWalletLog.getMoney());
    //             vo.setDrawSn(userWalletLog.getDrawSn());
    //             vo.setCashMoney(userWalletLog.getCashMoney());
    //             vo.setCreateTime(userWalletLog.getCreateTime());
    //             vo.setStatus(userWalletLog.getStatus());
    //             list.add(vo);
    //         });
    //     }
    //     return list;
    // }


    @Override
    public List<UserWalletLogListVo> userWalletRemainingSum(Long userId,UserWalletLogDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);

        List<UserWalletLogListVo> listVos = new ArrayList<>();
        int startTime = 0;
        int endTime = 0;
        if (StrUtil.isNotEmpty(dto.getTime())){
            //当月开始时间
            startTime = TimeUtil.beginOfMonth(TimeUtil.unixTime(dto.getTime()));

            //当月结束时间
            endTime = TimeUtil.endOfMonth(TimeUtil.unixTime(dto.getTime()));
        }
        List<UserWalletLog> list = baseMapper.userWalletRemainingSum(page, userId, startTime, endTime, EUserWalletLogType.toRebate.getValue(), EUserWalletLogType.toAgent.getValue(), EUserWalletLogType.cash.getValue());
        list.forEach(userWalletLog -> {
            UserWalletLogListVo vo = new UserWalletLogListVo();
            vo.setId(userWalletLog.getId());
            vo.setMoney(CommonUtil.getMoneyModified(userWalletLog.getMoney()));
            vo.setType(userWalletLog.getType());
            vo.setDrawSn(userWalletLog.getDrawSn());
            vo.setStatus(userWalletLog.getStatus());
            vo.setCreateTime(userWalletLog.getCreateTime());
            // vo.setCashMoney(userWalletLog.getCashMoney());
            listVos.add(vo);
        });
        return listVos;
    }


    @Override
    public List<UserWalletLogListVo> userWalletLogListInfo(Long userId, UserWalletLogDto dto,Integer start,Integer end) {
        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);

        List<UserWalletLogListVo> listVos = new ArrayList<>();
        int startTime = 0;
        int endTime = 0;
        if (StrUtil.isNotEmpty(dto.getTime())){
            //当月开始时间
            startTime = TimeUtil.beginOfMonth(TimeUtil.unixTime(dto.getTime()));

            //当月结束时间
            endTime = TimeUtil.endOfMonth(TimeUtil.unixTime(dto.getTime()));
        }
        List<UserWalletLog> list = baseMapper.userWalletLogListInfo(page, userId, startTime, endTime, start, end);
        list.forEach(userWalletLog -> {
            UserWalletLogListVo vo = new UserWalletLogListVo();
            vo.setId(userWalletLog.getId());
            vo.setMoney(CommonUtil.getMoneyModified(userWalletLog.getMoney()));
            vo.setType(userWalletLog.getType());
            vo.setDrawSn(userWalletLog.getDrawSn());
            vo.setStatus(userWalletLog.getStatus());
            vo.setCreateTime(userWalletLog.getCreateTime());
            // vo.setCashMoney(userWalletLog.getCashMoney());
            listVos.add(vo);
        });
        return listVos;
    }


    @Override
    public UserWalletLogDetailsVo userWalletLogDetails(IdDto dto) {
        LambdaQueryWrapper<UserWalletLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWalletLog::getId,dto.getId());
        UserWalletLog userWalletLog = getOnly(wrapper);
        UserWalletLogDetailsVo vo = BeanUtil.copyProperties(userWalletLog, UserWalletLogDetailsVo.class);

        //有订单编号 返回店铺信息
        if (!ObjectUtil.isEmpty(vo)){
            if (vo.getDrawSn() != null){
                LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(Order::getStoreId).eq(Order::getOrderSn,vo.getDrawSn());
                Order order = orderMapper.selectOne(queryWrapper);

                if (order != null){
                    LambdaQueryWrapper<Store> storeWrapper = new LambdaQueryWrapper<>();
                    storeWrapper.select(Store::getName).eq(Store::getId,order.getStoreId());
                    Store store = storeMapper.selectOne(storeWrapper);

                    if (store != null){
                        vo.setStoreName(store.getName());
                    }
                }
            }
        }
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean transferWallet(Long userId, UserWalletLogTransferDto dto) {

        if (dto.getMoney().compareTo(BigDecimal.ZERO) < 1){
            throw new GeneralException(HttpStatus.shiftToMoneyError);
        }

        User user = userService.getInfo(userId);

        // 记录转出 转入余额
        if (dto.getType().equals(ETransferType.rebate.getValue())) {

            addInfo(userId, dto.getMoney().negate(), SnowflakeUtil.appNextId(), EUserWalletLogType.outRebate.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

            addInfo(userId, dto.getMoney(), SnowflakeUtil.appNextId(), EUserWalletLogType.toRebate.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

        } else if (dto.getType().equals(ETransferType.agent.getValue())) {
            //判断用户是否是代理
            if (!CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue())){
                throw new GeneralException(HttpStatus.notAgentError);
            }
            addInfo(userId, dto.getMoney().negate(), SnowflakeUtil.appNextId(), EUserWalletLogType.outAgent.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

            addInfo(userId, dto.getMoney(), SnowflakeUtil.appNextId(), EUserWalletLogType.toAgent.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

        } else if (dto.getType().equals(ETransferType.active.getValue())) {
            //判断用户是否是达人
            if (!CommonUtil.bitExistOffset(user.getRole(), EUserRole.promotion.getValue())){
                throw new GeneralException(HttpStatus.notPromotionError);
            }

            addInfo(userId, dto.getMoney().negate(), SnowflakeUtil.appNextId(), EUserWalletLogType.outPromotion.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

            addInfo(userId, dto.getMoney(), SnowflakeUtil.appNextId(), EUserWalletLogType.toPromotion.getValue(), TimeUtil.unixTime(), EStatus.on.getValue());

        }

        return true;
    }

    @Override
    public IPage<UserWalletListLogVo> walletLogList(UserWalletLogListDto dto) {
        Page page = new Page<>(dto.getPage(), dto.getSize());

        LambdaQueryWrapper<UserWalletLog> wrapper = new LambdaQueryWrapper<>();
        if (dto.getUserId() != null){
            wrapper.eq(UserWalletLog::getUserId,dto.getUserId());
        }
        if (StrUtil.isNotEmpty(dto.getNickname())){
            List<Long> userIds = userMapper.nicknameByUserId(dto.getNickname());
            if (userIds.isEmpty()){
                return new Page<>();
            }
            wrapper.in(UserWalletLog::getUserId,userIds);
        }
        if (StrUtil.isNotEmpty(dto.getPhone())){
            Long userId = userMapper.phoneByUserId(dto.getPhone());
            if (userId == null){
                return new Page<>();
            }
            wrapper.eq(UserWalletLog::getUserId,userId);
        }
        if (dto.getType() != null){
            wrapper.eq(UserWalletLog::getType,dto.getType());
        }
        Page<UserWalletLog> userWalletLogPage = baseMapper.selectPage(page, wrapper);
        IPage<UserWalletListLogVo> walletIPage = userWalletLogPage.convert(userWalletLog -> BeanUtil.copyProperties(userWalletLog, UserWalletListLogVo.class));
        List<UserWalletListLogVo> walletListLog = walletIPage.getRecords();

        if (!walletListLog.isEmpty()){

            List<Long> userIds = walletListLog.stream().map(UserWalletListLogVo::getUserId).toList();

            //查询用户信息
            List<User> users = userMapper.getUserByIds(userIds);
            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user));

            for (UserWalletListLogVo vo:walletListLog) {

                if (userMap.containsKey(vo.getUserId())){
                    User user = userMap.get(vo.getUserId());
                    vo.setNickname(user.getNickname());
                    vo.setPhone(user.getPhone());
                    vo.setAvatarUrl(AppConfigUtil.getUrlPrefix(user.getAvatar()));
                }
            }
        }
        return walletIPage;
    }


    @Override
    public boolean deleteWalletLog(Long orderSn, Long userId, Integer type) {
        LambdaQueryWrapper<UserWalletLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserWalletLog::getDrawSn,orderSn)
                .eq(UserWalletLog::getUserId,userId)
                .eq(UserWalletLog::getType,type);
        baseMapper.delete(wrapper);
        return true;
    }


}
